<?php
/**
 * Управления jqGrid
 * 
 * <code>
 *  // базовое использования.
 *  // Внимание, Arm_Grid_jqGrid не проверяет данные на серверной стороне!
 *  // Ваши модели должны сами проверять поступившие данные, на коректность.
 *  // Если произошла ошибка бросьте исключительную ситуацию, grid выведет сообщение пользователю.
 *       $model = new User_Model_User();
 *       $grid  = new Arm_Grid_JqGrid('user');
 *       $grid->setModel($model, 'id', 'getUsers');
 *       $grid->setManipulationMethods('updateUser', 'deleteUser', 'createNewUser');
 *       // если модель наследует Zend_Db_Table то для установки модели хватает одного метода
 *       // $grid->setModel($model, 'id'); // использовать $grid->setManipulationMethods() нет не обходимости
 *       // установка столбцов, в самом простом виде выглядет так
 *       $grid->addColumn('id', '№');
 *       $grid->addColumn('login', Arm_Translate::_('Логин'));
 *       $grid->addColumn('initial', Arm_Translate::_('Ф.И.О.'));
 *       // если не нужно редактирования, убрать кнопки для управления данными:
 *       // $grid->getParams()->setNotEdit()
 *       $grid->getParams()->setTitleTable('Управления Пользвателями');
 *       $grid->render();
 *       // если grid обнаружит запрос на управления код ниже выполнятся не будет.
 *       // автомтичесий вывод, или создайте нужный вывод в шаблоне вида см. Arm/Grid/_temaplate/example.phtml
 *       $this->view->grid = $grid->getHtml();
 * </code>
 * <code>
 *   // Использования Zend_Config пример /modules/user/configs/application.ini
 *       $grid  = new Arm_Grid_JqGrid(null, null, Arm_Module::getInstance()->getConfig('user')->grids->user);
 *       // если grid обнаружит запрос на управления код ниже выполнятся не будет.
 *       $grid->render();
 *       // автомтичесий вывод, или создайте нужный вывод в шаблоне вида см. Arm/Grid/_temaplate/example.phtml
 *       $this->view->grid = $grid->getHtml();
 * </code>
 * @link http://www.secondpersonplural.ca/jqgriddocs/index.htm
 * @link http://trirand.com/blog/jqgrid/jqgrid.html
 * @author nrnwest@gmail.com
 *
 */
class Arm_Grid_JqGrid
{
    /**
     * Arm_Grid_JqGrid_Params
     * Общие параметры для grid
     * 
     * @var Arm_Grid_JqGrid_Params
     */
    private $_paramsGrid = null;
    
    /**
     * Объект модели который отвечает за получения, обновления, удаления, создания данных.
     * @var object
     */
    private $_model = null;
    
    /**
     * Фильтер для данных
     * @var Zend_Filter_Interface
     */
    private $_filter = null;
    
    /**
     * Ключи соотвествуют значениям передаваемым jqGrid в ключе oper=
     * при выполнении определенных данных.
     * Значения методы модели.
     * 
     * @var array
     */
    private $_modelMethods = array('edit'=>'update',
                                   'del'=>'delete',
                                   'add'=>'insert',
                                   'select'=>'select'
                                   );
    /**
     * Cтолбец содержащий id записей.
     * Устанавливается во время установки модели.
     * 
     * @var string
     */
    private $_idCol = null;
    
    /**
     * Стили которые подключаем
     * @var array
     */
    private $_styles = array(0=>'/jquery-ui-1.7.2.custom.css',
                             1=>'/css/ui.multiselect.css',
                             2=>'/css/ui.jqgrid.css'
                                 );
    /**
     * Тема оформления ui jQery 
     * @var string
     */                             
    private $_theme = 'redmond';
    
    /**
     * Базовый путь к темам ui jQery
     * @var unknown_type
     */
    private $_baseUi = '/scripts/jquery/plugins/ui/css/';
    /**
     * Подключаемые скрипты
     * @var array
     */
    private $_scripts = array(0=>'/js/i18n/grid.locale-ru.js',
                              1=>'/js/jquery.jqGrid.min.js',
                              2=> '/js/jquery-ui-1.7.2.custom.js'
                              );
    
    /**
     * Базовый путь для подключения js, css
     * @var string
     */
    private $_basePath = '/scripts/jquery/plugins/jgGrid';
    
    /**
     * Столбцы грида.
     * 
     * @var array
     */
    private $_columns = array();
                                   
    /**
     * Конструктор
     * @param string $idGrid
     * @param string|null $url
     */
    public function __construct($idGrid=null, $url=null, Zend_Config  $config = null)
    {
        if($idGrid === null and $config === null) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Вы должны указать или $idGrid, или задать масив конфига $config'));
        }
        
        $this->_paramsGrid = new Arm_Grid_JqGrid_Params($idGrid, $url, $config, $this);
    }
    
    /**
     * Установка базового пути для js и css
     * @param string $path
     */
    public function setBasePath($path)
    {
      $path = trim($path, '/');
      $this->_basePath = '/' . $path;
      return;
    }
    
    /**
     * Добавления столбца к grid
     * @param Arm_Grid_JqGrid_Col|string $column
     * @param string $label заголовок для столбца.
     * @return Arm_Grid_JqGrid_Col
     */
    public function addColumn($column, $label = null,  array  $config=array())
    {
        if(is_string($column)) {
            if($label === null) {
                $label = $column;
            }
            $column = new Arm_Grid_JqGrid_Col($column, $label, $config);
        }
        
        if(($column instanceof Arm_Grid_JqGrid_Col) === false) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Не верный тип объекта, требуеться Arm_Grid_JqGrid_Col'));
        }
        $this->_columns[$column->getName()] = $column;
        return $column;
    }
    
    /**
     * Вернет столбец.
     * 
     * @param string $name
     * @return Arm_Grid_JqGrid_Col
     */
    public function getColumn($name)
    {
        if(array_key_exists($name, $this->_columns) === false) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Не существует столбца с именем "%s"', $name));
        }
        return $this->_columns[$name];
    }
    
    /**
     * Строка с сформированая с перечнем label
     * 
     * @return string|false false если нет еще устновленных столбцов.
     */
    public function getColumnsLabelStr()
    {
       $result = array();
       foreach ($this->_columns as $v) {
           $result[] = "'" . $v->getLabel() . "'";
       }
       if($result === array()) {
           return false;
       }
       return implode(',', $result);
    }
    
    /**
     * Строка сформированная для вставки в ColModel
     * 
     * @return string|false false если нет еще устновленных столбцов.
     */
    public function getColumnsModelStr()
    {
        $result = array();
        foreach ($this->_columns as $v) {
            $result[] = $v->render();        
        }
        if($result === array()) {
           return false;
        }
        return implode(',' . "\n", $result);
    }
    
    /**
     * Вернет масив содержащий имена столбцов в гриде.
     * 
     * @return array
     */
    public function getColumnsName()
    {
        return array_keys($this->_columns);
    }
    
    /**
     * Arm_Grid_JqGrid_Params
     * 
     * @return Arm_Grid_JqGrid_Params
     */
    public function getParams()
    {
        return $this->_paramsGrid;
    }
    
    /**
     * Установка обьекта параметров
     * @param Arm_Grid_JqGrid_Params $params
     */
    public function setParams(Arm_Grid_JqGrid_Params $params)
    {
        $this->_paramsGrid = $params;
    }
    
    /**
     * Установка модели управления данными.
     * @param object $model обьект модели который должен содержать методы, через которые происходит 
     *                      управления данными. Если у вас данные хранятся в одной таблице, 
     *                      Вы можете создать обьект Zend_Db_Table
     * @param string $idCol названия столбца который содержит id данных.
     * @param string $select метод для получения данных, данный метод Должен возвращать Zend_Db_Select
     */
    public function setModel($model, $idCol='id', $select='select')
    {
        if(is_object($model) === false) {
            throw new Arm_Grid_Exception(Arm_Translate::_('Ошибка параметер $model, должен быть объект'));
        }
        $this->_model = $model;
        $this->_idCol = $idCol;
        $this->_existsMethodModel($select);
        $this->_modelMethods['select'] = $select;
    }
    
    /**
     * Установка столбца который содержит уникальный id записей grid
     * @param string $name
     */
    public function setIdCol($name)
    {
        $this->_idCol = $name;
    }
    
    /**
     * Вернет названия id столбца
     * 
     * @return string
     */
    public function getIdCol()
    {
        return $this->_idCol;
    }
    
    /**
     * Установка тем отображения внешнего вида grid, тему это ui jquery
     * @param string $theme
     */
    public function setTheme($theme)
    {
        $path = Arm_Core::getPathPublicHtml() . 'scripts/jquery/plugins/ui/css/' . $theme;
        if(!is_dir($path)) {
           throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Не существует темы ui, полный путь "%s"', $theme));
        }
        $this->_theme = $theme;
    }
    
    /**
     * Проверка установлена ли модель
     * 
     * @throw Arm_Grid_JqGrid_Exception
     */
    protected function _checkModel()
    {
        if($this->_model === null) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Вы должны задать обьект модели, setModel'));
        }
        return;
    }
    
    /**
     * Названия методов в модели которые отвечают за управления данными.
     * По умолчнию они соотвестуют методам Zend_Db_Table но
     * данные методы должны проверять данные которые поступают к ним.
     * 
     * Метод update,вызываются с двумя параметрами $data $id 
     * Параметр $data содержит ключ [id], ваш метод должен учитывать это.  
     * 
     * Метод delete вызывается с одинм параметроем $id id записи.
     * 
     * Метод insert вызывается с параметров $data с ключами полей которые заполнил пользователь.
     * 
     * @param string $update метод в модели, который отвечает за обновления
     * @param string $delete метод в модели, отвечает за удаления
     * @param string $insert метод в модели, отвечает за создания новой записи.
     */
    public function setManipulationMethods($update='update', $delete='delete', $insert='insert')
    {
        $this->_checkModel();
        // проверка правильности указания методов.
        $this->_existsMethodModel($update);
        $this->_existsMethodModel($delete);
        $this->_existsMethodModel($insert);
        
        $this->_modelMethods['edit'] = $update;
        $this->_modelMethods['del']  = $delete;
        $this->_modelMethods['add']  = $insert;
        return;
    }
    
    /**
     * Установка филтра который может отфильтровать значения для грид.
     * Через данный фильтер можно полностью управлять данными в grid.
     * 
     * @param  Zend_Filter_Interface|string $filter
     */
    public function setFilter($filter)
    {
        if(is_string($filter)) {
            $filter = new $filter();
        }
        if(false === ($filter instanceof Zend_Filter_Interface) ) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Фильтер должен реализововать интерфейс Zend_Filter_Interface'));
        }
        $this->_filter = $filter;
        return;
    }
    
    /**
     * Проверит существует ли мотод в модели, если нет бросит исключение.
     * 
     * @throw Arm_Grid_Exception
     * @param string $method
     * @return null
     */
    private function _existsMethodModel($method)
    {
        if($this->_model === null) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('не установленна модель, используйте методо setModel'));
        }
        if(method_exists($this->_model, $method)) {
            return;    
        }
        throw new Arm_Grid_Exception(Arm_Translate::_('Не существует метода: "%s" в установленой вами модели: "%s"', array($method, get_class($this->_model))));
    }
    
    /**
     * Выполнения, вывод grid, выполнения все не обходимых операций с данными.
     * 
     * @return bool false вывод html кода grid не нужно true вывод нужен
     */
    public function render()
    {
        
        // при срабатывании одного с трех условий выклчаем  вывод шаблонов, слоев.
        // Проверка поиск или нет.
        $request = Arm_Core::getRequest();
        if($request->isPost() === false or $request->isXmlHttpRequest() === false) {
            return true;
        }
        
        if($request->getParam('_search') === 'true') {
            $this->_checkModel();
            $this->_disableViews();
            $this->_returnSearch();
            return false;
        }
        // Проверка что выполняется запрос для получения данных
        if($request->getParam('_search') === 'false') {
            $this->_checkModel(); 
            $this->_disableViews();
            $this->_returnData();
            return false;
        } 
        // Проверка если запрос на манипулирования данными
        if($request->getParam('oper', '') !== '') {
            $this->_checkModel();
            $this->_disableViews();
            $this->_returnManipuliation($request->getParam('oper'));
            return false;
        }
        return true;
    }
    
    /**
     * Ищет по запросу пользователя данные, на основе обьекта select модели.
     * 
     * @return void
     */
    public function _returnSearch()
    {
        $request = Arm_Core::getRequest();
        $group   = $request->getPost('groupOp', 'AND');
        $filters = Zend_Json::decode($request->getPost('filters'));
        $select  = $this->_getSelectModel();
        $db      = $select->getAdapter();
        
        $iFilter = 0;
        
        foreach ($filters['rules'] as $v) {
            if($iFilter === 0) {
                $m = 'where';
            } else {
                if($group === 'AND') {
                    $m = 'where';
                } else {
                    $m = 'orWhere';
                }
            }
            switch ($v['op']) {
            	case Arm_Grid_JqGrid_Col::SEARCH_EQ:    
            	$where = $db->quoteIdentifier($v['field']) . ' = ' . $db->quote($v['data']);
            	break;
            	case Arm_Grid_JqGrid_Col::SEARCH_NE:    
                $where = $db->quoteIdentifier($v['field']) . ' != ' . $db->quote($v['data']);
                break;
            	case Arm_Grid_JqGrid_Col::SEARCH_CN:    
                $where = $db->quoteIdentifier($v['field']) . ' like ' . $db->quote('%'.$v['data'].'%');
                break;
                case Arm_Grid_JqGrid_Col::SEARCH_BW:    
                $where = $db->quoteIdentifier($v['field']) . ' like ' . $db->quote($v['data'].'%');
                break;
            }
            $select->{$m}($where);
            
        }
        $key = sprintf('%u', crc32($where));
        $key = str_replace('-', '', $key);
        $this->_returnData($select, $key);
    }
    
    /**
     * Zend_Cache_Core
     * 
     * @return Zend_Cache_Core
     */
    protected function _getCache()
    {
       $cache = Arm_Cache::getInstance()->getFrontendCore();
       $cache->setOption('cache_id_prefix', 'arm_grid_id_' . $this->getParams()->getIdGrid());
       return $cache;
    }
    
    /**
     * Выполняет запрос на измениния данных, автоматически сбрасывате кэш, грида. 
     * 
     * @return void 
     */
    public function _returnManipuliation($gridMethod)
    {
        if(array_key_exists($gridMethod, $this->_modelMethods) === false) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Изменен api grid нет метода "%s" для управления данными
            в текущем классе', $gridMethod));
        }
        $methodModel = $this->_modelMethods[$gridMethod];
        $this->_existsMethodModel($methodModel);
        
        $data = $this->_getDataInModel();
        $id   = $data['id'];
        unset($data['id']);
        try {
        if($gridMethod === 'edit') {
             if($id === null) {
                 throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Получен id с значением null, возможно ошибка в шаблоне вида'));
             }
            // вызов метода
            $methodSelect = $this->_modelMethods['select'];
            if($this->_model instanceof Zend_Db_Table) {
                // создадим where
                /*@var $db Zend_Db_Adapter_Abstract */
                $db = $this->_model->getAdapter();
                $this->_model->update($data, $db->quoteInto($this->_idCol . '=?', $id));
            } else {
               $this->_model->{$methodModel}($data, $id);
            }
            $this->_getCache()->clean(); 
            $this->_sendMessage(Arm_Translate::_('Обновленно'));
        }else if($gridMethod === 'add') {
            $this->_model->{$methodModel}($data);
            $this->_getCache()->clean(); 
            $this->_sendMessage(Arm_Translate::_('Добавленно'));
            
        }else if($gridMethod === 'del') {
            if($id === null) {
                 throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Получен id с значением null, возможно ошибка в шаблоне вида'));
             }
             if($this->_model instanceof Zend_Db_Table) {
                  $db = $this->_model->getAdapter();
                  $this->_model->delete($db->quoteInto($this->_idCol . '=?', $id));
             } else {
                  $this->_model->{$methodModel}($id);
             }
            $this->_getCache()->clean(); 
            $this->_sendMessage(Arm_Translate::_('Удаленно'));
        }
        } catch (Exception $e) {
           $this->_sendMessage($e->getMessage(), true);
        }
    }
    
    /**
     * Вернет массив данных полученных с post запроса
     * на основе имен установленных столбцов.
     * 
     * @return array
     */
    protected function _getDataInModel()
    {
       //@todo ко всем именам столбцов нужно добавлять префикс, иначе могут быть конфликты
       // или сделать ограничение на имена, наверное будет проще.
       $request = Arm_Core::getRequest();
       $data = array();
       foreach ($this->getColumnsName() as $v) {
           // не устанавливаем ключ id, id будет записан через ключ jqGrid
           if($v === $this->_idCol) {
               continue;
           }
           $data[$v] = $request->getPost($v);
       }
       $id = $request->getPost('id');
       $data['id'] = $id;
       return $data;
    }
    
    /**
     * Возвращает данные для заполнения grid.
     * Данные кэшируеются с учетом страницы, сортировки, количества запесей, запросов поиска.
     * Кэширования включаеться через главный конфиг системы.
     * Сброс кэша происходит автоматом, если в grid происходит изменения данных.
     * 
     * @param null $select
     * @param null $addKeyCache
     */
    public function _returnData($select=null, $addKeyCache=null)
    {
        if($select === null) {
           $select = $this->_getSelectModel(); 
        }
        $request = Arm_Core::getRequest();
        // добавляем сортировку
        if($request->getPost('sidx', '') !== '') {
           $this->getParams()->setSortname($request->getPost('sidx'));
           $this->getParams()->setSortorder($request->getPost('sord', 'asc')); 
        }
        // добавляем количество рядов
        if($request->getPost('rows', '') !== '') {
            $this->getParams()->setRowNum($request->getPost('rows')); 
        }
        if($this->getParams()->getParam('sortname') !== null) {
            $select->order($this->getParams()->getParam('sortname') . ' ' . $this->getParams()->getParam('sortorder'));
        }
        
        $page = $request->getPost('page') === null ? 1:$request->getPost('page'); 
        // кешируем результат работы.
        // создаем ключ для кеширования. кешируем не только paginator но и дальнейшую обработку.
        $cache = $this->_getCache();
        
        $key  = 'page_' . $page . '_' . $this->getParams()->getParam('sortname') . 
        $this->getParams()->getParam('sortorder') . 
        $this->getParams()->getParam('rowNum') . 
        $addKeyCache;
        
        if(false !== $cache->test($key)) {
            return $this->_sendResultJson($cache->load($key));
            // код ниже не выполняется если есть данные в кэше.
        }
        
        $paginator = Zend_Paginator::factory($select);       
        $paginator->setCurrentPageNumber($page);
        $paginator->setItemCountPerPage($this->getParams()->getParam('rowNum'));
        $data = $paginator->getCurrentItems();
        if($data instanceof Zend_Db_Table_Rowset) {
            $data = $data->toArray();
        } else {
            $data = (array)$data;
        }
        
        //передаем данные фильтру если установлен
        if($this->_filter !== null) {
            $data = $this->_filter->filter($data);
        }
        
        // формируем результатирующий масив
        $result = array();
        $result['page']    = $page;
        $result['total']   = $paginator->count();
        $result['records'] = $paginator->getTotalItemCount();
        $rows = array();
        
        $columns = array();
        // столбцы для которых не нужно устанавливать данные, вместо данных пустая строка.
        $notSetData =  array();
        /*@var $col Arm_Grid_JqGrid_Col */
        foreach ($this->_columns as $col) {
             if($col->getDadaNoGrid()) {
                 $notSetData[] = $col->getName();
             } 
             $columns[] = $col->getName();
        }
        $i = 0;
        if(is_array($data) === false) {
            throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Результатирующие даные должны быть массивом'));
        }
        // проверка что не ошиблись в задачи id ключа
        if($data !== array()) {
            if(array_key_exists($this->_idCol, $data[0]) === false) {
                throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Ошибка в задачи поля id, поля "%s" не существует в результатируеющем
                массиве', $this->_idCol));
            } 
        }
        foreach ($data as $k=>$v) {
            $rows[$i]['id']=$v[$this->_idCol];
            $cell = array();
            foreach ($columns as $c) {
              if(array_key_exists($c, $v) === false) {
                  throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('В результатирующих данных нету столбца заднного в grid
                  названия столбца "%s" столбцы существующие в ряде данных "%s"', array($c, implode(',', array_keys($v)))));
              }
                  if(array_search($c, $notSetData) !== false) {
                      $cell[]  = '';
                      continue;
                  }
                  $cell[] = $v[$c];  
            }
            $rows[$i]['cell']=$cell;
            $i++;
        }
        $result['rows'] = $rows;
        $cache->save($result, $key);
        $this->_sendResultJson($result);
    }
    
    /**
     * Отправка результата ф формате json
     * 
     * @param mixed $result
     */
    protected function _sendResultJson($result)
    {
        /*@var $response Zend_Controller_Response_Http */
        $response = Zend_Controller_Front::getInstance()->getResponse();
        $response->clearAllHeaders();
        $response->setBody(Zend_Json::encode($result));
        $response->setHeader('Content-Type', 'application/json');
        $response->sendResponse();
        exit;
    }
    
    /**
     * Отправка сообщения.
     * @param string $message
     */
    protected function _sendMessage($message, $error=false)
    {
        $message  = str_replace(':', '-', $message);
        $response = Zend_Controller_Front::getInstance()->getResponse();
        $response->clearAllHeaders();
        if($error) {
            $response->setBody('error:' . $message);
        } else {
            $response->setBody('success:' . $message);    
        }
        $response->sendResponse();
        exit;
    }
    
    /**
     * Zend_Db_Select
     * 
     * @return Zend_Db_Select
     */
    protected function _getSelectModel()
    {
        $method = $this->_modelMethods['select'];
        $select = $this->_model->$method();
        if($select instanceof Zend_Db_Select) {
            return $select;
        }
        throw new Arm_Grid_JqGrid_Exception(Arm_Translate::_('Установленная модель через свой методо select должна возвращать
         объект Zend_Db_Select'));
    }
    
    
    
    /**
     * Выключения вывода.
     */
    protected function _disableViews()
    {
        if (null !== ($layout = Zend_Layout::getMvcInstance())) {
                $layout->disableLayout();
            }
            Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->setNoRender(true);
    }
    
    /**
     * Возвращает html код, для вывода grid
     */
    public function getHtml()
    {
        // установка подключаемых скриптов.
        $this->setBasePath($this->_basePath);
        // Подклчаем языковый файл проверяем есть ли он если нету включаем по умолчанию.
        // даный файл должен быть первым.
        $lang = Arm_Translate::getInstance()->getLanguage();
        $pathLangDefault = '/js/i18n/grid.locale-'.Arm_Translate::getInstance()->getLanguageDefault().'.js';
        $pathLang = '/js/i18n/grid.locale-' . $lang . '.js';
        if(is_file(Arm_Core::getPathPublicHtml() . ltrim($this->_basePath, '/') . $pathLang) === false) {
            $pathLang = $pathLangDefault;
        }
        $this->_scripts[0] = $pathLang;
        foreach ($this->_scripts as $k=>$v) {
            $this->_scripts[$k] = $this->_basePath . '/' . ltrim($v, '/');
        }
        
        // Подключаем тему.
        $this->_styles[0]  = $this->_baseUi . $this->_theme . $this->_styles[0];
        foreach ($this->_styles as $k=>$v) {
            if($k === 0) {
                $this->_styles[$k] = $v;
                continue;
            }
            $this->_styles[$k] = $this->_basePath . '/' . ltrim($v, '/');     
        }
        
       // Получем обьект вида
       $viewRender = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
       /*@var $view Zend_View */
       if($viewRender->view !== null) {
           $view = clone $viewRender->view;
       } else {
           $view = new Zend_View();
       }
       $view->setScriptPath(dirname(__FILE__) . '/JqGrid/_template/');
       // установка параметров
       $view->styles    = $this->_styles;
       $view->scripts   = $this->_scripts;
       $view->params    = $this->getParams();
       // формирования ответа
       $body = $view->render('base.phtml');
       //Zend_Controller_Front::getInstance()->getResponse()->setBody($body);
       return $body;
    }
}